﻿using System.Collections;
using System.Reflection;
using Microsoft.Extensions.Caching.Memory;
using SqlSugar;

namespace Digitalmes.Sugar;

/// <summary>
/// SqlSugar二级缓存
/// </summary>
public sealed class SugarMemoryCache : ICacheService
{
    private readonly IMemoryCache _memoryCache;

    public SugarMemoryCache(IMemoryCache memoryCache)
    {
        _memoryCache = memoryCache;
    }

    public void Add<V>(string key, V value)
    {
        _memoryCache.Set(key, value);
    }

    public void Add<V>(string key, V value, int cacheDurationInSeconds)
    {
        _memoryCache.Set(key, value, DateTimeOffset.Now.AddSeconds(cacheDurationInSeconds));
    }

    public bool ContainsKey<V>(string key)
    {
        return _memoryCache.TryGetValue(key, out _);
    }

    public V Get<V>(string key)
    {
        return _memoryCache.Get<V>(key);
    }

    public IEnumerable<string> GetAllKey<V>()
    {
        const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic;

        //var entries = _memoryCache.GetType().GetField("_entries", flags).GetValue(_memoryCache);

        //.NET 7
        var coherentState = _memoryCache.GetType().GetField("_coherentState", flags)!.GetValue(_memoryCache);
        var entries = coherentState!.GetType().GetField("_entries", flags)!.GetValue(coherentState);

        List<string> keys = new();
        if (entries is not IDictionary items)
            return keys;

        foreach (DictionaryEntry cacheItem in items)
        {
            keys.Add(cacheItem.Key.ToString()!);
        }
        return keys;
    }

    public V GetOrCreate<V>(string cacheKey, Func<V> create, int cacheDurationInSeconds = int.MaxValue)
    {
        if (!_memoryCache.TryGetValue<V>(cacheKey, out var value))
        {
            value = create();
            _memoryCache.Set(cacheKey, value);
        }
        return value;
    }

    public void Remove<V>(string key)
    {
        _memoryCache.Remove(key);
    }
}
